﻿#include "libcard.h"

#define MAX_BUF_SIZE		256
//#define DEBUG

#define STX 0x02
#define ETX 0x03

typedef struct{
	rf_card* card;
	int uart_fd;
	pthread_mutex_t* card_mutex;
	pthread_t thread_id;
	bool seek_card_flag;//false:退出寻卡 true:开始寻卡
}card_t;

card_t g_card;
int err_count = 0;
uint8 cardState = 0x45;// （0x59） 寻卡成功   （0x4E） 寻卡不成功    （0x45） 卡机内无卡  （0x57） 卡不在允许操作的位置上

int get_valid_bcc(const uint8* buf, const uint32 len)
{
	uint32 index = 0;
	uint8 bcc = 0;
	uint32 data_len = 0;
	uint32 i = 0;

	if (buf==NULL || buf[0] != STX)
		return -1;

	data_len = (buf[1]<<8) | buf[2];
	data_len +=4;
	for(i=0; i<data_len; i++){
		bcc ^= buf[index+i];
	}

	return bcc;
}

uint8 get_tran_data_length(const uint8* buf, const uint32 len)
{
	uint8 data_len = 0;
	uint8 index = 0;

	for(index=0;index<len;index++){
		if(buf[index] == STX)
			break;
	}
	if(index >= len)
		return 0;

	for(;index<len;index++){
		if(buf[index] == ETX)
			break;
		data_len++;
	}

	data_len -= 3;
	return data_len;
}

int is_recv_complete(uint8* buf, int len)
{
	int index = 0;
	int data_len = 0;

	if(buf == NULL)
		return -1;

	if(buf[0] != STX)
		return -1;

	data_len = (buf[1]<<8) |buf[2];
	index = data_len+3;//ETX index


	if(buf[index] == 0x03){
#ifdef DEBUG
		printf("##Libcard TAITAN M1## data recv complete\n");
#endif
		return 0;
	}

#ifdef DEBUG
	printf("##Libcard TAITAN M1## data recv no complete\n");
#endif
	return 1;

}

int uart_send(const int fd, const uint8 *buf, const uint32 len)
{
	int sended = 0;
	int i;

	if((fd<=0) || (buf==NULL) ){
		printf("##Libcard TAITAN M1## uart send fail,due to para err!\n");
		return -1;
	}

	sended = write(fd, buf, len);
	if( sended <= 0){
		printf("##Libcard TAITAN M1##--Port send [%d] error.\n ", sended);
		g_card.card->errcode = 1;//通信异常
	}

#ifdef DEBUG
	printf("SEND[%03d] -->", sended);
	for(i=0; i < sended; i++) {
		printf("%02x ", buf[i]);
	}
	printf("\n");
#endif
	return sended;
}

int listen_recv(const int fd, uint8 *buf, int rlen, int timeout)
{
	int len = 0, total_len = 0;
	int count =0;
	int ret;
	int i = 0;
	fd_set fdset;
	int check_ret = -1;
	uint8 *p = NULL;
	struct timeval tm;

	if (fd < 0 || rlen<0 || rlen> MAX_BUF_SIZE){
		printf(" ##Libcard TAITAN M1## listen_recv fail, due to param err !\n");
		return -1;
	}

	p = buf;
	tm.tv_sec = timeout/1000;
	tm.tv_usec = (timeout%1000)*1000;

	while(count<3)
	{
		FD_ZERO(&fdset);
		FD_SET(fd, &fdset);
		ret = select(fd + 1, &fdset, NULL, NULL, &tm);
		if(ret < 0){
			perror("##Libcard TAITAN M1## select failued !\n ");
			break;
		}
		else if(ret == 0){
			++count; //timeout
		}
		else if(FD_ISSET(fd, &fdset)){
			rlen = rlen-len;
			if(rlen <= 0)
				break;//buffer已接满

			len = read(fd, buf, rlen);
			if(len < 0)
				break;

			total_len += len;
			check_ret = is_recv_complete(p,total_len);
			if(check_ret == 0)
				break;
			else if(check_ret == 1){
				buf = p+total_len;
				continue;
			}
			else{
				printf("##Libcard TAITAN M1## Recv Trash Data\n");
				break;
			}
		}
	}

	if(total_len <= 0){
#ifdef DEBUG
		printf("##Libcard TAITAN M1## listen_recv fail: without recv data or recv err!!!\n");
#endif
		return total_len;
	}

	int bcc1 = 0,bcc2 = 0;
	bcc1 = get_valid_bcc(p,total_len);
	bcc2 = p[total_len-1];
#ifdef DEBUG
	printf("RECV[%03d]-->",len);
	for(i=0; i<total_len; i++)
		printf("%02x ",p[i]);
	printf("\n");
	printf("##Libcard TAITAN M1## card recv data bbc1=%02x, bbc2=%02x\n",bcc1,bcc2);
#endif
	if((bcc1 != bcc2) || (bcc1 == -1))
		return -1;
	return total_len;
}

int port_open(card_uart_para *port)
{
	int fd = 0;
	card_uart_para *com = port;

	if(NULL == com)	return -1;

	//打开串口设备
	fd = open(com->name, O_RDWR|O_NOCTTY|O_NONBLOCK);
	if(fd < 0) {
		printf("##Libcard TAITAN M1##--Open PORT: [%s] failure.\n", com->name);
	}
	return fd;
}

int speed_to_flag(int speed)
{
	uint32 i;
	int cnt = 0;

	for (i = 0; i < sizeof(speed_arr)/sizeof(int); i++) {
		cnt = (speed - speed_arr[i]);
		if ( cnt == 0)
			return baudflag_arr[i];
	}

	printf("##Libcard TAITAN M1##--Unsupported baudrate, use 9600 instead!\n");
	return B9600;
}

int port_setup(int fd, card_uart_para *port)
{
	card_uart_para *com = port;
	struct termios old_tio, new_tio;
	int baud_rate = 0;

	if(fd < 0)		return -1;
	if(NULL == com)		return -1;

	tcgetattr(fd, &old_tio);
	bzero(&new_tio, sizeof(struct termios));
	new_tio.c_cflag |= (CLOCAL | CREAD);

	//设置波特率
	baud_rate = speed_to_flag(com->baud);
	new_tio.c_cflag |= baud_rate;
	//设置停止位
	switch(com->stop_bits) {
	case 1:
		new_tio.c_cflag &= ~CSTOPB;
		break;
	case 2:
		new_tio.c_cflag |= CSTOPB;
		break;
	default:
		printf("##Libcard TAITAN M1##--PORT stop bits set error. use default.\n");
		new_tio.c_cflag &= ~CSTOPB;
		break;
	}

	//设置奇偶校验
	switch(com->parity) {
	case 0://无校验
		new_tio.c_cflag &= ~PARENB;
		break;
	case 1://奇校验
		new_tio.c_cflag |= (PARENB | PARODD);
		break;
	case 2://偶校验
		new_tio.c_cflag |= PARENB;
		new_tio.c_cflag &= ~PARODD;
		break;
	case 3://MARK校验
		new_tio.c_cflag |= (PARENB | PARODD);
		new_tio.c_cflag |= CMSPAR;
		break;
	case 4://SPACE校验
		new_tio.c_cflag |= PARENB;
		new_tio.c_cflag &= ~PARODD;
		new_tio.c_cflag |= CMSPAR;
		break;
	default:
		printf("##Libcard TAITAN M1##--PORT parity set error. use default.\n");
		new_tio.c_cflag &= ~PARENB;
		break;
	}
	new_tio.c_cflag &= ~CSIZE;
	switch(com->data_bits) {
	case 5:
		new_tio.c_cflag |= CS5;
		break;
	case 6:
		new_tio.c_cflag |= CS6;
		break;
	case 7:
		new_tio.c_cflag |= CS7;
		break;
	case 8:
		new_tio.c_cflag |= CS8;
		break;
	default:
		printf("##Libcard TAITAN M1##--PORT data bits set error. use default.\n");
		new_tio.c_cflag |= CS8;
		break;
	}

	//设置无硬件流控
	new_tio.c_cflag &= ~CRTSCTS;
	new_tio.c_lflag = 0;
	new_tio.c_oflag = 0;
	new_tio.c_cc[VMIN] = 1;
	new_tio.c_cc[VTIME] = 0;
	new_tio.c_iflag &= ~(IXON | IXOFF | IXANY);

	cfsetispeed(&new_tio, baud_rate);
	cfsetospeed(&new_tio, baud_rate);
	tcsetattr(fd, TCSANOW, &new_tio);
	tcflush(fd, TCIFLUSH);

	return 0;
}

void setTimer(unsigned int seconds, unsigned int mseconds)
{
	struct timeval temp;

	temp.tv_sec = seconds + (mseconds/1000);
	temp.tv_usec = (mseconds%1000)*1000;

	select(0, NULL, NULL, NULL, &temp);

	return ;
}

//检查版本,同时检测读卡器的通信是否断开
void* protocol_check_ver(void* arg)
{
	//	uint8 cmd[7] = {0x02,0x00,0x02,0x31,0x11,0x20,0x03};
	uint8 cmd[7] = {0x02,0x00,0x02,0x34,0x30,0x03,0x07};
	uint8 data[MAX_BUF_SIZE] = {0};
	int re_len = 0;

	while(1){
		printf("##Libcard TAITAN M1## check card version state: errcode=%02d  cardState=%c\n",g_card.card->errcode,cardState);

		memset(data,0,sizeof(data));
		setTimer(1,0);

		pthread_mutex_lock(g_card.card_mutex);
		if((uart_send(g_card.uart_fd, cmd, sizeof(cmd))) < 0){
			printf("##Libcard TAITAN M1## check card versio  send error\n");
			g_card.card->errcode = 1;//通信异常
			pthread_mutex_unlock(g_card.card_mutex);
			continue;
		}

		re_len = listen_recv(g_card.uart_fd, data, sizeof(data),1000);
		if(re_len <= 0){
			if(err_count >= 3){
				printf("##Libcard TAITAN M1## check card versio listen_recv timeout or error!\n");
				g_card.card->errcode = 1;//通信异常
			}
			err_count++;
			pthread_mutex_unlock(g_card.card_mutex);

			continue;
		}

		cardState=data[5];

		if(cardState!=0x59  && cardState!=0x4E && cardState!=0x45 && cardState!=0x57){
			if(err_count > 3){
				g_card.card->errcode = 1;//连续3次检查版本失败，通信异常
				printf("##Libcard TAITAN M1## check card version , card reponse error, errcode=%02d !\n",g_card.card->errcode);
			}

			err_count++;
			pthread_mutex_unlock(g_card.card_mutex);
			continue;
		}

		g_card.card->errcode = 0;//通信正常
		err_count = 0;

		pthread_mutex_unlock(g_card.card_mutex);
	}

	return NULL;
}

//初始化函数，pcard指向一个rf_card结构， plock指向pthread_mutex_t互斥量, 指向sem_t信号量,在检测到刷卡时置位。//返回0成功，1 失败
int protocol_card_init(void * pcard, void *plock, void *psem)
{
	int fd = 0;

	if((pcard==NULL) || (plock==NULL) || (psem==NULL)){
		printf("##libcard error## card init fail, due to init para NULL!\n");
		return 1;
	}

	g_card.card = (rf_card*)pcard;
	g_card.card_mutex=(pthread_mutex_t*)plock;
	g_card.card->com.baud=9600;

	if((fd = port_open(&(g_card.card->com))) == -1 )
	{
		printf("##libcard error## open device fail\n");
		return 1;
	}

	g_card.uart_fd = fd;
	port_setup(g_card.uart_fd,&(g_card.card->com));
	pthread_create(&g_card.thread_id,NULL,protocol_check_ver,NULL);

	printf("##libcard Init##uart name:%s uart baud:%d uart data_bit:%d uart parity:%d uart stop_bits:%d \n",g_card.card->com.name, g_card.card->com.baud,g_card.card->com.data_bits, g_card.card->com.parity, g_card.card->com.stop_bits);
	printf("##libcard Init## card source pointer:%p   libcard card pointer:%p \n",pcard,(g_card.card));

	return 0;
}


//激活卡函数，delaytime 等待时间，cardtype 返回的卡类型，UIDLen返回的卡号长度，cardUID指向一个32字节大小的内存，用于存储返回的卡号。
int protocol_enabled_card(short delaytime, char *cardtype, unsigned char *UIDLen, char * cardUID) //返回0成功，1 失败
{
	int count = 0;
	//uint8 cmd[] = {0x02,0x00,0x04,0x32,0x24,0x00,0x00,0x16,0x03};
	uint8 cmd[] = {0x02,0x00,0x02,0x34,0x31,0x03,0x06};
	uint8 data[MAX_BUF_SIZE]={0};
	int len = 0, index = 0, i = 0;
	unsigned int delay = (unsigned int)delaytime;

	printf("##Libcard TAITAN M1## begin enable card...\n");

	while(count < 60)//如果连续60次没有探测到卡则退出
	{
		if(g_card.seek_card_flag != true){
			printf("##Libcard TAITAN M1## exit seek card status!\n");
			return 1;
		}

		pthread_mutex_lock(g_card.card_mutex);

		memset(data,0,sizeof(data));
		setTimer(0,delay);
		if((uart_send(g_card.uart_fd,cmd,sizeof(cmd))) < 0 )
		{
			printf("##Libcard TAITAN M1## enable card  send error\n");
			count++;
			if(err_count >= 3){
				g_card.card->errcode = 1;//通信异常
				err_count = 0;
				goto  FAIL;
			}

			pthread_mutex_unlock(g_card.card_mutex);
			continue;
		}

		if((len = listen_recv(g_card.uart_fd, data, sizeof(data), 1000)) <= 0)
		{
			printf("##Libcard TAITAN M1## enable card  recv error\n");
			count++;
			if(err_count >= 3){
				g_card.card->errcode = 1;//通信异常
				err_count = 0;
				goto FAIL;
			}
			err_count++;
			pthread_mutex_unlock(g_card.card_mutex);
			continue;
		}

		for(index=0; index<len; index++){
			if(data[index] == STX)
				break;
		}

		if(data[index+5] == 0x59)//获取卡序列号成功，返回卡序列号
		{
			printf("##Libcard TAITAN M1## enable card success.\n");
			//g_card.card->cardtype = data[index+5];
			//*cardtype = data[index+5];
			printf("---cardtype = NULL\n",g_card.card->cardtype);
			//	*UIDLen = data[index+6];
			*UIDLen = 4;
			//	g_card.card->UIDLen = data[index+6];
			g_card.card->UIDLen = 4;
			for(i=0;i<g_card.card->UIDLen;i++)
				g_card.card->cardUID[i] = data[index+6+i];
			memcpy(cardUID,g_card.card->cardUID,g_card.card->UIDLen);

			pthread_mutex_unlock(g_card.card_mutex);
			return 0;
		}
		else if(data[index+5] == 0x4e){
			printf("##Libcard TAITAN M1##get card fail.\n");
			pthread_mutex_unlock(g_card.card_mutex);
			return 1;
		}
		else if(data[index+5] == 0x45)
		{
			printf("##Libcard TAITAN M1##no card.\n");
			pthread_mutex_unlock(g_card.card_mutex);
			return 1;
		}
		else{
			printf("##Libcard TAITAN M1##card enter , count=%d\n",count);
			count++;			
			pthread_mutex_unlock(g_card.card_mutex);			
			continue;
		}
	}

	if(count >= 60)
	{
		printf("##Libcard TAITAN M1## enable card fail count > 60!!!\n");
		//pthread_mutex_unlock(g_card.card_mutex);
		return 1;
	}

	FAIL:
	printf("##Libcard TAITAN M1## enable card fail  ,errode=%d !!!\n",g_card.card->errcode);
	pthread_mutex_unlock(g_card.card_mutex);
	return 1;

}

void clear_card_info(void)
{
	memset(&(g_card.card->UIDLen),0,sizeof(unsigned char));
	memset(g_card.card->cardUID,0,sizeof(g_card.card->cardUID));
	memset(g_card.card->cmd1,0,sizeof(g_card.card->cmd1));
	memset(g_card.card->cmd2,0,sizeof(g_card.card->cmd2));
	memset(g_card.card->cmd3,0,sizeof(g_card.card->cmd3));
	memset(g_card.card->cardNUM,0,sizeof(g_card.card->cardNUM));
	memset(&(g_card.card->available_money),0,sizeof(unsigned int));
	memset(&(g_card.card->ver),0,sizeof(char));
	memset(&(g_card.card->tag),0,sizeof(char));
	memset(&(g_card.card->rand),0,sizeof(int));
	memset(&(g_card.card->mac),0,sizeof(int));
}

int protocol_key_a_section0()
{
	//uint8 cmd[] = {0x02,0x00,0x04,0x32,0x24,0x00,0x00,0x16,0x03};
	uint8 cmd_key_a_0[] = {0x02,0x00,0x09,0x34,0x32,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x0e};
	uint8 data[MAX_BUF_SIZE]={0};
	int re_len = 0, index = 0, i = 0;

	pthread_mutex_lock(g_card.card_mutex);
	if(uart_send(g_card.uart_fd, cmd_key_a_0, sizeof(cmd_key_a_0)) < 0){
		printf("##Libcard TAITAN M1##  read  card fail, due to send cmd_key_a_0 error\n");
		goto fail;
	}
	memset(data,0,sizeof(data));
	re_len = listen_recv(g_card.uart_fd, data, sizeof(data), 1000);
	if(re_len <= 0){
		printf("##Libcard TAITAN M1## read  card fail, due to recv cmd_key_a_0 error!\n");
		goto fail;
	}
	else{
		for(index=0;index<re_len;index++){
			if(data[index] == STX)
				break;
		}
		if(data[index+6] == 0x59){
			printf("key_a_section0 success\n");
			pthread_mutex_unlock(g_card.card_mutex);
			return 0;
		}
		else
		{
			printf("key_a_section0 fail\n");
			goto fail;
		}
	}

	fail:
	clear_card_info();
	pthread_mutex_unlock(g_card.card_mutex);
	return 1;
}
int protocol_key_a_section1()
{
	uint8 cmd_key_a_1[] = {0x02,0x00,0x09,0x34,0x32,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x0f};
	uint8 data[MAX_BUF_SIZE]={0};
	int re_len = 0, index = 0, i = 0;

	pthread_mutex_lock(g_card.card_mutex);
	if(uart_send(g_card.uart_fd, cmd_key_a_1, sizeof(cmd_key_a_1)) < 0){
		printf("##Libcard TAITAN M1##  read  card fail, due to send cmd_key_a_1 error\n");
		goto fail;
	}
	memset(data,0,sizeof(data));
	re_len = listen_recv(g_card.uart_fd, data, sizeof(data), 1000);
	if(re_len <= 0){
		printf("##Libcard TAITAN M1## read  card fail, due to recv cmd_key_a_1 error!\n");
		goto fail;
	}
	else{
		for(index=0;index<re_len;index++){
			if(data[index] == STX)
				break;
		}
		if(data[index+6] == 0x59){
			printf("key_a_section1 success\n");
			pthread_mutex_unlock(g_card.card_mutex);
			return 0;
		}
		else
		{
			printf("key_a_section1 fail\n");
			goto fail;
		}
	}

	fail:
	clear_card_info();
	pthread_mutex_unlock(g_card.card_mutex);
	return 1;
}
int protocol_key_a_section2()
{
	uint8 cmd_key_a_2[] = {0x02,0x00,0x09,0x34,0x32,0x02,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x0c};
	uint8 data[MAX_BUF_SIZE]={0};
	int re_len = 0, index = 0, i = 0;

	pthread_mutex_lock(g_card.card_mutex);
	if(uart_send(g_card.uart_fd, cmd_key_a_2, sizeof(cmd_key_a_2)) < 0){
		printf("##Libcard TAITAN M1##  read  card fail, due to send cmd_key_a_2 error\n");
		goto fail;
	}
	memset(data,0,sizeof(data));
	re_len = listen_recv(g_card.uart_fd, data, sizeof(data), 1000);
	if(re_len <= 0){
		printf("##Libcard TAITAN M1## read  card fail, due to recv cmd_key_a_2 error!\n");
		goto fail;
	}
	else{
		for(index=0;index<re_len;index++){
			if(data[index] == STX)
				break;
		}
		if(data[index+6] == 0x59){
			printf("key_a_section2 success\n");
			pthread_mutex_unlock(g_card.card_mutex);
			return 0;
		}
		else
		{
			printf("key_a_section2 fail\n");
			goto fail;
		}
	}

	fail:
	clear_card_info();
	pthread_mutex_unlock(g_card.card_mutex);
	return 1;
}


int protocol_read_user_id()
{
	uint8 cmd_user_id[] = {0x02,0x00,0x04,0x34,0x33,0x00,0x01,0x03,0x03};
	uint8 data[MAX_BUF_SIZE]={0};
	int re_len = 0, index = 0, i = 0;

	pthread_mutex_lock(g_card.card_mutex);
	if(uart_send(g_card.uart_fd, cmd_user_id, sizeof(cmd_user_id)) < 0){
		printf("##Libcard TAITAN M1##  read_user_id, due to send cmd_user_id error\n");
		goto fail;
	}
	memset(data,0,sizeof(data));
	re_len = listen_recv(g_card.uart_fd, data, sizeof(data), 1000);
	if(re_len <= 0){
		printf("##Libcard TAITAN M1## read  card fail, due to recv read_user_id error!\n");
		goto fail;
	}
	else{
		for(index=0;index<re_len;index++){
			if(data[index] == STX)
				break;
		}
		if(data[index+7] == 0x59){
			printf("read_user_id success\n");
			index+=9;
			for(i=0;i<16;i++)
				g_card.card->cardNUM[i] = data[index+i];
			pthread_mutex_unlock(g_card.card_mutex);
			return 0;
		}
		else
		{
			printf("read_user_id fail\n");
			goto fail;
		}
	}

	fail:
	clear_card_info();
	pthread_mutex_unlock(g_card.card_mutex);
	return 1;
}

int protocol_read_user_money()
{
	uint8 cmd_money[] = {0x02,0x00,0x04,0x34,0x33,0x02,0x00,0x03,0x00};
	uint8 data[MAX_BUF_SIZE]={0};
	int re_len = 0, index = 0, i = 0;

	pthread_mutex_lock(g_card.card_mutex);
	if(uart_send(g_card.uart_fd, cmd_money, sizeof(cmd_money)) < 0){
		printf("##Libcard TAITAN M1##  read_user_id, due to send cmd_money error\n");
		goto fail;
	}
	memset(data,0,sizeof(data));
	re_len = listen_recv(g_card.uart_fd, data, sizeof(data), 1000);
	if(re_len <= 0){
		printf("##Libcard TAITAN M1## read  card fail, due to recv cmd_money error!\n");
		goto fail;
	}
	else{
		for(index=0;index<re_len;index++){
			if(data[index] == STX)
				break;
		}
		if(data[index+7] == 0x59){
			printf("cmd_money success\n");
			index+=9;
			//for(i=0;i<16;i++)
			g_card.card->available_money = data[12]>>24 | data[11]>>16 | data[10]>>8 | data[9] ;
			pthread_mutex_unlock(g_card.card_mutex);
			return 0;
		}
		else
		{
			printf("cmd_money fail\n");
			goto fail;
		}
	}

	fail:
	clear_card_info();
	pthread_mutex_unlock(g_card.card_mutex);
	return 1;
}


//读卡查询函数，money 返回卡余额，locknum 返回灰锁次数。  //返回0成功，1 失败
int protocol_read_card(float *money, char *locknum) 
{
	short delaytime = 250;
	int re_len = 0;
	int i = 0, j = 0;
	char cardtype[1]={0};
	unsigned char UIDLen[1]={0};
	char cardUID[64]={0};
	unsigned char data[MAX_BUF_SIZE];
	int index = 0;
	uint8 count=0;

	clear_card_info();
	g_card.seek_card_flag = true;

	while(g_card.seek_card_flag==true  && count<60){
		printf("##Libcard TAITAN M1## seeking card, count=%d\n",count);
		if(cardState==0x59)
			break;
		count++;
		setTimer(0,500);
	}

	if(g_card.seek_card_flag==false || count>=60){
		return 1;
	}

	printf("##Libcard TAITAN M1## begin read card...\n");
	if (g_card.card->errcode  !=  0){
		printf("##Libcard TAITAN M1## read card fail, due to card is err! errcode=%d\n",g_card.card->errcode);
		return 1;
	}

	if(protocol_key_a_section0() == 1){
		printf("##Libcard TAITAN M1## read card  fail ,due to protocol_key_a_section0 fail\n");
		return 1;
	}
	else{
		if(protocol_read_user_id()==1){
			printf("##Libcard TAITAN M1## read card  fail ,due to protocol_read_user_id fail\n");
			return 1;
		}
	}

	if(protocol_key_a_section2() == 1){
		printf("##Libcard TAITAN M1## read card  fail ,due to protocol_key_a_section2 fail\n");
		return 1;
	}
	else{
		if(protocol_read_user_money() == 1){
			printf("##Libcard TAITAN M1## read card  fail ,due to protocol_read_user_money fail\n");
			return 1;
		}
	}

	printf("############ Card Info ##################\n");
	printf("card.type = %x\n",g_card.card->cardtype);
	printf("card.UIDLen = %d\n",g_card.card->UIDLen);
	printf("card.cardUID = ");
	for(i=0; i<g_card.card->UIDLen; i++)
		printf("%02x ", g_card.card->cardUID[i]);
	printf("\n");
	printf("card.cardNUM = ");
	for(i=0; i<8; i++)
		printf("%02x",g_card.card->cardNUM[i]);
	printf("\n");
	printf("card.ver = %02x\n",g_card.card->ver);
	printf("card.money = %d\n",g_card.card->available_money);
	printf("############    Card  End ##################\n");
	return 0;
}



int protocol_exit_seek_card_status(void)
{
	g_card.seek_card_flag = false;
	printf("##Libcard TAITAN M1## exit seek card!\n");
	return 0;
}
